package com.blockmeta.bbs.businesslibrary.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.GradientDrawable;
import androidx.annotation.ColorInt;
import androidx.annotation.IdRes;
import androidx.constraintlayout.widget.ConstraintLayout;
import android.util.AttributeSet;

import com.blockmeta.bbs.baselibrary.utils.DimentionsUtil;
import com.blockmeta.bbs.businesslibrary.R;

/**
 * @author AirThor
 * @date 2019/9/30.
 */
public class CornerAndTagsConstraintLayout extends ConstraintLayout {
    private float topLeftRadius;
    private float topRightRadius;
    private float bottomLeftRadius;
    private float bottomRightRadius;

    private boolean mBackgroundEnable;
    protected boolean mTagEnable;
    protected boolean mStrokeEnable;
    private @IdRes int mTagIconRes;
    private Bitmap mTagIcon;
    private @ColorInt int mStrokeColor;

    private Paint mRoundPaint;
    private Paint mLayerPaint;
    private Paint mStrokePaint;

    private RectF mRectF = new RectF();
    private RectF mStrokeRectF = new RectF();
    private Path mStrokePath = new Path();
    private Rect mTagRect = new Rect();
    private float mStrokeWidth;
    private int mBackGroundColor;

    public CornerAndTagsConstraintLayout(Context context) {
        super(context);
        init(context,null);
    }

    public CornerAndTagsConstraintLayout(Context context, AttributeSet attrs) {
        super(context,attrs);
        init(context,attrs);
    }

    public CornerAndTagsConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        if (attrs!=null){
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CornerAndTagsConstraintLayout);
            float radius = ta.getDimension(R.styleable.CornerAndTagsConstraintLayout_ctsRadius,0);
            topLeftRadius = ta.getDimension(R.styleable.CornerAndTagsConstraintLayout_ctsTopLeftRadius, radius);
            topRightRadius = ta.getDimension(R.styleable.CornerAndTagsConstraintLayout_ctsTopRightRadius, radius);
            bottomLeftRadius = ta.getDimension(R.styleable.CornerAndTagsConstraintLayout_ctsBottomLeftRadius, radius);
            bottomRightRadius = ta.getDimension(R.styleable.CornerAndTagsConstraintLayout_ctsBottomRightRadius, radius);
            mBackgroundEnable = ta.getBoolean(R.styleable.CornerAndTagsConstraintLayout_ctsBackgroundEnable,false);
            mStrokeEnable = ta.getBoolean(R.styleable.CornerAndTagsConstraintLayout_ctsStrokeEnable,false);
            mTagIconRes = ta.getResourceId(R.styleable.CornerAndTagsConstraintLayout_ctsTagIcon,R.drawable.icon_selected_tag);

            mTagEnable = ta.getBoolean(R.styleable.CornerAndTagsConstraintLayout_ctsTagEnable,false);

            mStrokeWidth = ta.getDimension(R.styleable.CornerAndTagsConstraintLayout_ctsStrokeWidth, 2);
            mStrokeColor = ta.getColor(R.styleable.CornerAndTagsConstraintLayout_ctsStrokeColor, Color.WHITE);
            mBackGroundColor = ta.getColor(R.styleable.CornerAndTagsConstraintLayout_ctsBackGroundColor, Color.WHITE);
            ta.recycle();

            if (mBackgroundEnable) {
                GradientDrawable backGround = new GradientDrawable();
                backGround.setColor(mBackGroundColor);
                if (topLeftRadius > 0 || topRightRadius > 0 || bottomLeftRadius > 0 || bottomRightRadius > 0) {
                    float[] radii = new float[]{
                            topLeftRadius, topLeftRadius,
                            topRightRadius, topRightRadius,
                            bottomRightRadius, bottomRightRadius,
                            bottomLeftRadius, bottomLeftRadius
                    };
                    backGround.setCornerRadii(radii);
                }
                setBackground(backGround);
            }
        }

        mRoundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRoundPaint.setColor(Color.WHITE);
        mRoundPaint.setAntiAlias(true);
        mRoundPaint.setStyle(Paint.Style.FILL);
        mRoundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));

        mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mStrokePaint.setStrokeWidth(DimentionsUtil.dp2px(context,mStrokeWidth));
        mStrokePaint.setColor(mStrokeColor);
        mStrokePaint.setStyle(Paint.Style.STROKE);

        mLayerPaint = new Paint();
        mLayerPaint.setXfermode(null);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mTagIcon = BitmapFactory.decodeResource(getContext().getResources(),mTagIconRes);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mTagIcon.recycle();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mRectF.set(0,0,w,h);
        int sideLength = h*5/14;
        mTagRect.set(0,0,sideLength,sideLength);
    }
    @Override
    public void dispatchDraw(Canvas canvas) {
        canvas.saveLayer(mRectF, mLayerPaint, Canvas.ALL_SAVE_FLAG);
        super.dispatchDraw(canvas);
        if (mTagEnable&&mTagIcon!=null){
            drawTagIcon(canvas);
        }
        if (mStrokeEnable){
            drawStroke(canvas);
        }
        drawTopLeft(canvas);
        drawTopRight(canvas);
        drawBottomLeft(canvas);
        drawBottomRight(canvas);
        canvas.restore();

    }

    private void drawStroke(Canvas canvas) {
        if (topLeftRadius == 0 && topRightRadius == 0 && bottomLeftRadius == 0 && bottomRightRadius == 0) {
            canvas.drawRect(0f, 0f, getWidth(), getHeight(), mStrokePaint);
            return;
        }
        mStrokePath.reset();
        if (topLeftRadius==0){
            mStrokePath.moveTo(0f,0f);
        }else {
            mStrokeRectF.set(0, 0, topLeftRadius * 2, topLeftRadius * 2);
            mStrokePath.addArc(mStrokeRectF,180,90);
        }

        mStrokePath.lineTo(getWidth()-topRightRadius,0);
        if (topRightRadius != 0){
            mStrokeRectF.set(getWidth()-topRightRadius*2,0,getWidth(),topRightRadius*2);
            mStrokePath.arcTo(mStrokeRectF,-90,90);
        }

        mStrokePath.lineTo(getWidth(),getHeight()-bottomRightRadius);
        if (bottomRightRadius!=0){
            mStrokeRectF.set(getWidth()-bottomRightRadius*2,getHeight()-bottomRightRadius*2,getWidth(),getHeight());
            mStrokePath.arcTo(mStrokeRectF,0,90);
        }

        mStrokePath.lineTo(bottomLeftRadius,getHeight());
        if (bottomLeftRadius!=0){
            mStrokeRectF.set(0,getHeight()-bottomLeftRadius*2,bottomLeftRadius*2,getHeight());
            mStrokePath.arcTo(mStrokeRectF,90,90);
        }
        mStrokePath.close();

        canvas.drawPath(mStrokePath,mStrokePaint);
    }

    private void drawTagIcon(Canvas canvas) {
        canvas.drawBitmap(mTagIcon,null,mTagRect,null);
    }

    private void drawTopLeft(Canvas canvas) {
        if (topLeftRadius > 0) {
            Path path = new Path();
            path.moveTo(0, topLeftRadius);
            path.lineTo(0, 0);
            path.lineTo(topLeftRadius, 0);
            path.arcTo(new RectF(0, 0, topLeftRadius * 2, topLeftRadius * 2),
                    -90, -90);
            path.close();
            canvas.drawPath(path, mRoundPaint);
        }
    }

    private void drawTopRight(Canvas canvas) {
        if (topRightRadius > 0) {
            int width = getWidth();
            Path path = new Path();
            path.moveTo(width - topRightRadius, 0);
            path.lineTo(width, 0);
            path.lineTo(width, topRightRadius);
            path.arcTo(new RectF(width - 2 * topRightRadius, 0, width,
                    topRightRadius * 2), 0, -90);
            path.close();
            canvas.drawPath(path, mRoundPaint);
        }
    }

    private void drawBottomLeft(Canvas canvas) {
        if (bottomLeftRadius > 0) {
            int height = getHeight();
            Path path = new Path();
            path.moveTo(0, height - bottomLeftRadius);
            path.lineTo(0, height);
            path.lineTo(bottomLeftRadius, height);
            path.arcTo(new RectF(0, height - 2 * bottomLeftRadius,
                    bottomLeftRadius * 2, height), 90, 90);
            path.close();
            canvas.drawPath(path, mRoundPaint);
        }
    }

    private void drawBottomRight(Canvas canvas) {
        if (bottomRightRadius > 0) {
            int height = getHeight();
            int width = getWidth();
            Path path = new Path();
            path.moveTo(width - bottomRightRadius, height);
            path.lineTo(width, height);
            path.lineTo(width, height - bottomRightRadius);
            path.arcTo(new RectF(width - 2 * bottomRightRadius, height - 2
                    * bottomRightRadius, width, height), 0, 90);
            path.close();
            canvas.drawPath(path, mRoundPaint);
        }
    }

    private GradientDrawable getBackGroundDrawable(){
        return (GradientDrawable) getBackground();
    }

    public void setBackGroundColor(@ColorInt int backGroundColor) {
        GradientDrawable gradientDrawable = getBackGroundDrawable();
        gradientDrawable.setColor(backGroundColor);
    }

    public void setTagEnable(boolean tagEnable) {
        mTagEnable = tagEnable;
    }

    public void setBackgroundEnable(boolean backgroundEnable) {
        mBackgroundEnable = backgroundEnable;
    }

    @Override
    public void setBackgroundColor(int color) {
        mBackGroundColor = color;
    }

    public void setStrokeEnable(boolean strokeEnable) {
        mStrokeEnable = strokeEnable;
    }
}
